﻿using Extented.UI.Core.Native;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Printing;
using System.Linq;
using System.Text;

namespace Extented.UI.Core.Utils
{
    public class GraphicsUnitConverter
    {
        static double GetScale(float fromDpi, float toDpi)
        {
            return (double)toDpi / (double)fromDpi;
        }
        static float ConvF(float val, double scale)
        {
            return (float)((double)val * scale) + 0f;
        }
        static double ConvD(double val, double scale)
        {
            return val * scale;
        }
        static int Conv(int val, double scale)
        {
            return System.Convert.ToInt32(val * scale);
        }
        static public Point Round(PointF point)
        {
            return new Point(System.Convert.ToInt32(point.X), System.Convert.ToInt32(point.Y));
        }
        static public Rectangle Round(RectangleF rect)
        {
            Point p = new Point(System.Convert.ToInt32(rect.Left), System.Convert.ToInt32(rect.Top));
            Size s = new Size(System.Convert.ToInt32((float)rect.Right) - p.X, System.Convert.ToInt32((float)rect.Bottom) - p.Y);
            return new Rectangle(p, s);
        }
        static public Rectangle Convert(Rectangle val, GraphicsUnit fromUnit, GraphicsUnit toUnit)
        {
            return Convert(val, GraphicsDpi.UnitToDpi(fromUnit), GraphicsDpi.UnitToDpi(toUnit));
        }
        static public Size Convert(Size val, GraphicsUnit fromUnit, GraphicsUnit toUnit)
        {
            return Convert(val, GraphicsDpi.UnitToDpi(fromUnit), GraphicsDpi.UnitToDpi(toUnit));
        }
        static public Point Convert(Point val, GraphicsUnit fromUnit, GraphicsUnit toUnit)
        {
            return Convert(val, GraphicsDpi.UnitToDpi(fromUnit), GraphicsDpi.UnitToDpi(toUnit));
        }
        static public RectangleF Convert(RectangleF val, GraphicsUnit fromUnit, GraphicsUnit toUnit)
        {
            return Convert(val, GraphicsDpi.UnitToDpi(fromUnit), GraphicsDpi.UnitToDpi(toUnit));
        }
        static public RectangleDF Convert(RectangleDF val, GraphicsUnit fromUnit, GraphicsUnit toUnit)
        {
            return Convert(val, GraphicsDpi.UnitToDpi(fromUnit), GraphicsDpi.UnitToDpi(toUnit));
        }
        static public SizeF Convert(SizeF val, GraphicsUnit fromUnit, GraphicsUnit toUnit)
        {
            return Convert(val, GraphicsDpi.UnitToDpi(fromUnit), GraphicsDpi.UnitToDpi(toUnit));
        }
        static public PointF Convert(PointF val, GraphicsUnit fromUnit, GraphicsUnit toUnit)
        {
            return Convert(val, GraphicsDpi.UnitToDpi(fromUnit), GraphicsDpi.UnitToDpi(toUnit));
        }
        static public MarginsF Convert(MarginsF val, GraphicsUnit fromUnit, GraphicsUnit toUnit)
        {
            return Convert(val, GraphicsDpi.UnitToDpi(fromUnit), GraphicsDpi.UnitToDpi(toUnit));
        }
        static public float Convert(float val, GraphicsUnit fromUnit, GraphicsUnit toUnit)
        {
            return Convert(val, GraphicsDpi.UnitToDpi(fromUnit), GraphicsDpi.UnitToDpi(toUnit));
        }
        static public Rectangle Convert(Rectangle val, float fromDpi, float toDpi)
        {
            if (fromDpi == toDpi)
                return val;
            return Round(Convert((RectangleF)val, fromDpi, toDpi));
        }
        static public Size Convert(Size val, float fromDpi, float toDpi)
        {
            if (fromDpi == toDpi)
                return val;
            double s = GetScale(fromDpi, toDpi);
            return new Size(Conv(val.Width, s), Conv(val.Height, s));
        }
        static public Point Convert(Point val, float fromDpi, float toDpi)
        {
            if (fromDpi == toDpi)
                return val;
            double s = GetScale(fromDpi, toDpi);
            return new Point(Conv(val.X, s), Conv(val.Y, s));
        }
        static public int Convert(int val, float fromDpi, float toDpi)
        {
            if (fromDpi == toDpi)
                return val;
            double s = GetScale(fromDpi, toDpi);
            return Conv(val, s);
        }
        static public RectangleF Convert(RectangleF val, float fromDpi, float toDpi)
        {
            if (fromDpi == toDpi)
                return val;
            double s = GetScale(fromDpi, toDpi);
            return RectangleF.FromLTRB(ConvF(val.Left, s), ConvF(val.Top, s), ConvF(val.Right, s), ConvF(val.Bottom, s));
        }
        static public RectangleDF Convert(RectangleDF val, float fromDpi, float toDpi)
        {
            if (fromDpi == toDpi)
                return val;
            double s = GetScale(fromDpi, toDpi);
            return RectangleDF.FromLTRB(ConvD(val.Left, s), ConvD(val.Top, s), ConvD(val.Right, s), ConvD(val.Bottom, s));
        }
        static public SizeF Convert(SizeF val, float fromDpi, float toDpi)
        {
            if (fromDpi == toDpi)
                return val;
            double s = GetScale(fromDpi, toDpi);
            return new SizeF(ConvF(val.Width, s), ConvF(val.Height, s));
        }
        static public PointF Convert(PointF val, float fromDpi, float toDpi)
        {
            if (fromDpi == toDpi)
                return val;
            double s = GetScale(fromDpi, toDpi);
            return new PointF(ConvF(val.X, s), ConvF(val.Y, s));
        }
        public static float Convert(float val, float fromDpi, float toDpi)
        {
            if (fromDpi == toDpi)
                return val;
            double s = GetScale(fromDpi, toDpi);
            return ConvF(val, s);
        }
        public static MarginsF Convert(MarginsF val, float fromDpi, float toDpi)
        {
            if (fromDpi == toDpi)
                return val;
            double s = GetScale(fromDpi, toDpi);
            MarginsF result = new MarginsF();
            result.Left = ConvF(val.Left, s);
            result.Right = ConvF(val.Right, s);
            result.Top = ConvF(val.Top, s);
            result.Bottom = ConvF(val.Bottom, s);
            return result;
        }
        public static Margins Convert(Margins val, float fromDpi, float toDpi)
        {
            if (fromDpi == toDpi)
                return val;
            double s = GetScale(fromDpi, toDpi);
            return new Margins(
                Conv(val.Left, s),
                Conv(val.Right, s),
                Conv(val.Top, s),
                Conv(val.Bottom, s));
        }
        static public RectangleF PixelToDoc(RectangleF val)
        {
            return Convert(val, GraphicsDpi.Pixel, GraphicsDpi.Document);
        }
        static public SizeF PixelToDoc(SizeF val)
        {
            return Convert(val, GraphicsDpi.Pixel, GraphicsDpi.Document);
        }
        static public PointF PixelToDoc(PointF val)
        {
            return Convert(val, GraphicsDpi.Pixel, GraphicsDpi.Document);
        }
        static public float PixelToDoc(float val)
        {
            return Convert(val, GraphicsDpi.Pixel, GraphicsDpi.Document);
        }
        static public RectangleF DocToPixel(RectangleF val)
        {
            return Convert(val, GraphicsDpi.Document, GraphicsDpi.Pixel);
        }
        static public SizeF DocToPixel(SizeF val)
        {
            return Convert(val, GraphicsDpi.Document, GraphicsDpi.Pixel);
        }
        static public PointF DocToPixel(PointF val)
        {
            return Convert(val, GraphicsDpi.Document, GraphicsDpi.Pixel);
        }
        static public float DocToPixel(float val)
        {
            return Convert(val, GraphicsDpi.Document, GraphicsDpi.Pixel);
        }
        static public MarginsF DocToPixel(MarginsF val)
        {
            return Convert(val, GraphicsDpi.Document, GraphicsDpi.Pixel);
        }
    }
}
